<template>
  <div class="voice-recorder">
    <el-icon
      v-if="!isRecording"
      class="mic start"
      :size="22"
      @click="startRecording"
    >
      <Microphone />
    </el-icon>
    <el-icon
      v-if="isRecording"
      class="mic stop"
      :size="22"
      @click="stopRecording"
    >
      <Mute />
    </el-icon>
  </div>
</template>

<script setup lang="ts">
import { ref, onUnmounted } from 'vue'
import { Microphone, Mute } from '@element-plus/icons-vue'
import Nls from '@/utils/ali-nls'

interface Props {
  disabled?: boolean
}

interface Emits {
  (e: 'textRecognized', text: string): void
  (e: 'recordingStart'): void
  (e: 'recordingStop'): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const isRecording = ref(false)

// 音频相关变量
let mediaStream: MediaStream | null = null
let processor: ScriptProcessorNode | null = null
let nlsInstance: any = null

// 工具函数：音频格式转换（Float32转Int16）
function convertFloat32ToInt16(buffer: Float32Array): Int16Array {
  const int16Array = new Int16Array(buffer.length)
  for (let i = 0; i < buffer.length; i++) {
    int16Array[i] = Math.min(1, buffer[i]) * 0x7fff
  }
  return int16Array
}

const startRecording = async () => {
  if (props.disabled) return

  try {
    const AudioContext = window.AudioContext || (window as any).webkitAudioContext
    const audioContext = new AudioContext({
      sampleRate: 16000,
    })

    const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
    isRecording.value = true
    mediaStream = stream
    emit('recordingStart')

    const source = audioContext.createMediaStreamSource(stream)
    processor = audioContext.createScriptProcessor(2048, 1, 1)

    // 这里需要实际的NLS实例，暂时注释掉
    nlsInstance = new Nls()
    nlsInstance.on((text: string) => {
      if (text === '获取nls token失败') {
        stopRecording()
        return
      }
      emit('textRecognized', text)
    })

    processor.onaudioprocess = (event) => {
      const pcmData = convertFloat32ToInt16(
        event.inputBuffer.getChannelData(0),
      )
      // 处理音频数据
      if (nlsInstance) {
        nlsInstance.send(pcmData.buffer)
      }
    }

    source.connect(processor)
    processor.connect(audioContext.destination)
  } catch (error) {
    console.error('录音启动失败:', error)
    isRecording.value = false
  }
}

const stopRecording = () => {
  if (mediaStream) {
    mediaStream.getTracks().forEach((track) => track.stop())
    mediaStream = null
  }
  if (processor) {
    processor.disconnect()
    processor = null
  }
  if (nlsInstance) {
    nlsInstance.close()
    nlsInstance = null
  }
  isRecording.value = false
  emit('recordingStop')
}

onUnmounted(() => {
  stopRecording()
})

// 暴露方法给父组件
defineExpose({
  stopRecording
})
</script>

<style lang="scss" scoped>
.voice-recorder {
  .mic {
    width: 32px;
    height: 32px;
    background-color: #2b6e50;
    border-radius: 8px;
    color: #fff;
    margin-right: 6px;
    cursor: pointer;

    &:hover {
      opacity: 0.8;
    }

    &.stop {
      background-color: #f44336;
    }
  }
}
</style>
